package ray.shader;

import java.util.ArrayList;

import ray.math.Color;
import ray.math.Point3;
import ray.math.Vector3;
import ray.surface.Surface;
import ray.Light;
import ray.Scene;
import ray.Intersection;
import ray.Ray;

/**
 * A Lambertian material scatters light equally in all directions. BRDF value is
 * a constant
 *
 * @author ags
 */
public class Lambertian implements Shader {
	
	/** The color of the surface. */
	protected final Color diffuseColor = new Color(1, 1, 1);
	public void setDiffuseColor(Color inDiffuseColor) { diffuseColor.set(inDiffuseColor); }
	
	public Lambertian() { }
	
	public void shade(Color colorOut, Scene scene, ArrayList<Light> lights, Vector3 eye, Intersection inter) {
		
		//Need to add each light source contribution to the final intersection point color
		Vector3 norm = new Vector3(inter.normal);
		Vector3 eyeDir = new Vector3(eye);
		norm.normalize();
		eyeDir.normalize();
		
		Point3 intersect = new Point3(inter.intersection);
		
		Color temp1 = new Color(0,0,0);
		
		for (int i=0; i<lights.size(); i++) 
		{
			Color temp2 = new Color(diffuseColor.r, diffuseColor.g, diffuseColor.b);
			if (!isShadowed(scene, lights.get(i), inter, scene.getSurfaces()))
			{
			Vector3 lightRay = new Vector3(lights.get(i).position.x - intersect.x, lights.get(i).position.y - intersect.y, lights.get(i).position.z - intersect.z);
			lightRay.normalize();
			temp2.scale(lights.get(i).intensity);
			temp2.scale(Math.max(0, norm.dot(lightRay)));
			temp1.add(temp2);
			}
		}
		colorOut.set(temp1);
	}
	
	/**
	 * @see Object#toString()
	 */
	public String toString() {
		
		return "lambertian: " + diffuseColor;
	}
	
	public boolean isShadowed(Scene scene, Light light, Intersection inter, ArrayList<Surface> surfaces) {
		
		Ray shadowRay = new Ray();
		
		// Setup the shadow ray to start at surface and end at light
		shadowRay.origin.set(inter.intersection);
		shadowRay.direction.sub(light.position, inter.intersection);
		shadowRay.tEnd = 1.0;
		
		int i = 0;
		boolean intersection;
		do{
			intersection = surfaces.get(i).intersect(inter, shadowRay);
			if(intersection)
				return intersection;
		i++;	
		}while(i < surfaces.size());
		return false;
	}
	}
